package com.js.statemachine.config.uml;

import com.js.statemachine.common.BizUniformResult;
import com.js.statemachine.common.ConditionConst;
import com.js.statemachine.common.EventConst;
import com.js.statemachine.config.StateMachineEventListener;
import com.js.statemachine.service.uml.MeterStateMachineBizInter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
import org.springframework.statemachine.config.model.StateMachineModelFactory;
import org.springframework.statemachine.guard.Guard;
import org.springframework.statemachine.uml.UmlStateMachineModelFactory;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

/**
 * @author ：js
 * @date ：Created in 2021-02-20 13:56
 * @description: 表计状态机配置
 * @version:1.0
 */
@Configuration
@Slf4j
@EnableStateMachineFactory(name = "meterStateMachineFactory")
@Scope("prototype")
public class MeterStateMachineConfig extends StateMachineConfigurerAdapter<String, String> {

	@Resource
	private StateMachineEventListener stateMachineEventListener;

	public static final String meterStateMachineId = "meter";

	@Autowired
	private MeterStateMachineBizInter meterStateMachineBizInter;


	@Override
	public void configure(StateMachineConfigurationConfigurer<String, String> config)
			throws Exception {
		config
				.withConfiguration().listener(stateMachineEventListener)
				.autoStartup(true).machineId(meterStateMachineId);
	}

	@Override
	public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
		model
				.withModel()
				.factory(meterFactory());
	}

	@Bean
	public StateMachineModelFactory<String, String> meterFactory() {
		return new UmlStateMachineModelFactory("classpath:Meter_State_Machine.uml");
	}

	/**
	 * 安装业务
	 *
	 * @return
	 */
	@Bean
	public Action<String, String> installBiz() {
		return context -> {
			log.info("安装测试!");
			try {
				//安装业务执行
				meterStateMachineBizInter.install(context.getMessage());
				BizUniformResult result = (BizUniformResult) context.getMessageHeader(ConditionConst.DTO);
				if (result.getFlag()) {
					//发送安装完成
					context.getStateMachine().sendEvent(EventConst.INSTALL_COMPLETED);
				} else {
					//安装失败
					context.getStateMachine().sendEvent(EventConst.INSTALL_FAIL);
				}
			} catch (Exception e) {
				log.error("安装业务出现异常:{}", e.getMessage());
				context.getStateMachine().hasStateMachineError();
				context.getStateMachine().sendEvent(EventConst.INSTALL_FAIL);
			}
		};
	}

	/**
	 * 拆表测试
	 *
	 * @return
	 */
	@Bean
	public Action<String, String> splitMeterBiz() {
		return context -> {
			log.info("拆表测试!");
			try {
				//解绑业务执行
				meterStateMachineBizInter.splitMeter(context.getMessage());
				BizUniformResult result = (BizUniformResult) context.getMessageHeader(ConditionConst.DTO);
				if (result.getFlag()) {
					//发送拆表完成
					context.getStateMachine().sendEvent(EventConst.SPLIT_METER_COMPLETED);
				} else {
					//拆表失败
					log.info("拆表失败!");
				}
			} catch (Exception e) {
				log.error("拆表业务出现异常:{}", e.getMessage());
				log.info("拆表失败!");
			}
		};
	}

	/**
	 * 检定测试
	 *
	 * @return
	 */
	@Bean
	public Action<String, String> docimasyBiz() {
		return context -> {
			log.info("检定测试!");
			boolean flag;
			try {
				//检定业务执行
				flag = meterStateMachineBizInter.docimasy(context.getMessage());
				if (flag) {
					//发送检定完成
					context.getStateMachine().sendEvent(EventConst.DOCIMASY_COMPLETE);
				} else {
					//检定失败
					log.info("检定失败!");
					//如果是从安装过来的
					if (ConditionConst.INSTALLIERT.equals(context.getMessageHeader(ConditionConst.PREMISE))) {
						context.getStateMachine().sendEvent(EventConst.DOCIMASY_FAIL_TO_INSTALL);
						//如果从未安装过来的
					} else if (ConditionConst.UNINSTALLIERT.equals(context.getMessageHeader(ConditionConst.PREMISE))) {
						context.getStateMachine().sendEvent(EventConst.DOCIMASY_FAIL_TO_UNINSTALL);
					}
				}
			} catch (Exception e) {
				log.error("出现异常");
				log.info("检定失败!");
			}
		};
	}

	/**
	 * 检定完成状态到安装或者未安装的判断条件
	 *
	 * @ return
	 */
	@Bean
	public Guard<String, String> needInstallGuard() {
		return context -> ObjectUtils.nullSafeEquals(ConditionConst.INSTALLIERT, context.getMessageHeaders().get(ConditionConst.CHOICE, String.class));
	}

	/**
	 * 检定到已安装所作的业务
	 *
	 * @ return
	 */
	@Bean
	public Action<String, String> reinstallation() {
		return context -> {
			//检定到已安装所作的业务
			meterStateMachineBizInter.reinstallation(context.getMessage());
		};
	}


}


